#include "AlgoEvaluatorModule3CPCD.h"
#include "AlgoCDP.h"

class algo::AlgoEvaluatorModule3CPCDPrivate 
{
public:
};

algo::AlgoEvaluatorModule3CPCD::AlgoEvaluatorModule3CPCD()
	: d(new AlgoEvaluatorModule3CPCDPrivate)
{
}

algo::AlgoEvaluatorModule3CPCD::~AlgoEvaluatorModule3CPCD()
{
	delete d;
}

std::vector<algobase::EvaluateEnvirDataType> algo::AlgoEvaluatorModule3CPCD::getNeedType()
{
	return std::vector<algobase::EvaluateEnvirDataType>({ algobase::EEDT_AreaSound });
}

int algo::AlgoEvaluatorModule3CPCD::exec(const algobase::Path& path, double& result, algobase::EvaluateModuleCoords& indexCoords)
{
	if (path.empty())
	{
		result = 1.0; // An empty path has a 100% chance of not being detected.
		indexCoords.clear();
		return 0;
	}

	auto db = getDB();
	if (!db) {
		setErrorMessage("DB is null");
		return -1;
	}

	// 1. Collect sonar efficiency (or detection probability) for each point.
	// Assuming the stored data is the probability of being DETECTED at that point/segment.
	std::vector<double> detection_probabilities;
	detection_probabilities.reserve(path.size());
	for (const auto& point : path) {
		// EEDT_AreaSound is assumed to provide the detection probability at this point.
		auto detection_prob = db->getData(algobase::EEDT_AreaSound, getTaskConfig().mStartTime, point.mCoordZ);
		detection_probabilities.push_back(detection_prob);
	}
	algo::CDP cdp;
	auto cpcd_result = cdp.calculateCPCD(detection_probabilities, 0.01, 1);
	// 2. Calculate the cumulative probability of NOT being detected.
	// The probability of not being detected at a single point is (1 - P_detection).
	// The cumulative probability over the path is the product of these individual probabilities.
	double cumulative_survival_prob = 1.0;
	indexCoords.resize(path.size());

	for (size_t i = 0; i < path.size(); ++i)
	{
		indexCoords[i].Assign(path[i]);
		// Store the cumulative survival probability up to this point.
		indexCoords[i].mRawValue = cpcd_result[i];
		indexCoords[i].mResult = calcScore(cpcd_result[i]);
	}

	// 3. The final result is the cumulative probability over the entire path.
	// This value is the "Raw Value" for the EL2IT_3CPCD index.
	result = calcScore(cpcd_result[path.size() - 1]);

	return 0;
}

double algo::AlgoEvaluatorModule3CPCD::calcScore(double rawValue) const
{
	return rawValue * getWeight();
}

double algo::AlgoEvaluatorModule3CPCD::calcRaw(const std::vector<double>& rawValues) const
{
	if (rawValues.empty()) {
		return 0.0;
	}
	else {
		return rawValues.back();
	}
}
